package smecta.client.print.service;

import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import smecta.client.print.domain.query.PageDTO;
import smecta.client.print.domain.query.Query;
import smecta.client.print.domain.query.SortQuery;
import smecta.client.print.util.web.CreateTimeModel;
import smecta.client.print.util.web.*;
//import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
import smecta.client.print.util.MyMapper;
import tk.mybatis.mapper.entity.Example;
import org.apache.commons.collections.CollectionUtils;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
public class BaseService<T> {

    @Autowired
    private MyMapper<T> mapper;
//    @Autowired
//    private TokenUtil tokenUtil;

    public List<T> select(T entity) {
        List<T> list = mapper.select(entity);
        invokeMethod(list, "unzip");
        return list;
    }

//    public PageDTO selectPageByQuery(Query query) {
//
//        ParameterizedTypeImpl typeImpl = (ParameterizedTypeImpl) getClass().getGenericSuperclass();
//        Class<?> modelClass = (Class<?>) typeImpl.getActualTypeArguments()[0];
//        Example example = new Example(modelClass);
//        if (StringUtils.isNotBlank(query.getSortBy())) {
//            if ("desc".equals(query.getOrder())) {
//                example.orderBy(query.getSortBy()).desc();
//            } else {
//                example.orderBy(query.getSortBy()).asc();
//            }
//        }
//
////        query2criteria(query, example);
//
//        return findPageListByExample(example);
//    }

//    public TableResultResponse<T> selectByQuery(Query query) {
//        ParameterizedTypeImpl typeImpl = (ParameterizedTypeImpl) getClass().getGenericSuperclass();
//        Class<?> modelClass = (Class<?>) typeImpl.getActualTypeArguments()[0];
//        Example example = new Example(modelClass);
//        if (StringUtils.isNotBlank(query.getSortBy())) {
//            if ("desc".equals(query.getOrder())) {
//
//                example.orderBy(query.getSortBy()).desc();
//            } else {
//                example.orderBy(query.getSortBy()).asc();
//            }
//        }
//        query2criteria(query, example);
//        Page<Object> result = PageHelper.startPage(query.getPage(), query.getLimit());
//        List<T> list = this.selectByExample(example);
//        return new TableResultResponse<T>(result.getTotal(), list);
//    }

    public void query2criteria(Query query, Example example) {
        if (query.entrySet().size() > 0) {
            Example.Criteria criteria = example.createCriteria();
            for (Map.Entry<String, Object> entry : query.entrySet()) {
                if (entry.getKey().equals("departmentKey")) {
                    criteria.andEqualTo(entry.getKey(), entry.getValue().toString());

                } else {
                    criteria.andLike(entry.getKey(), "%" + entry.getValue().toString() + "%");

                }
            }
        }
    }


    public T selectOne(T entity) {
        T model = mapper.selectOne(entity);
        invokeMethod(model, "unzip");
        return model;
    }

    public T selectByPrimaryKey(Object primaryKey) {
        T model = mapper.selectByPrimaryKey(primaryKey);
        invokeMethod(model, "unzip");
        return model;
    }

    public int updateByPrimaryKeySelective(T entity) {
//        UserInfoModel userInfoModel = tokenUtil.getUserInfoByTenantContext();
//        final String loginName = userInfoModel != null ? userInfoModel.getUserName() : "系统";
        final String loginName =  "系统";
        invokeMethod(entity, "zip");
        makeEdit(entity, loginName);
        return mapper.updateByPrimaryKeySelective(entity);
    }

    public int insertSelective(T entity) {

//        UserInfoModel userInfoModel = tokenUtil.getUserInfoByTenantContext();
//        final String loginName = userInfoModel != null ? userInfoModel.getUserName() : "系统";
        final String loginName =  "系统";
        invokeMethod(entity, "zip");
        makeCreate(entity, loginName);
        return mapper.insertSelective(entity);

    }

    public int insertList(List<T> entityList) {
        if (CollectionUtils.isEmpty(entityList)) {
            return 0;
        }
//        UserInfoModel userInfoModel = tokenUtil.getUserInfoByTenantContext();
//        final String loginName = userInfoModel != null ? userInfoModel.getUserName() : "系统";
        final String loginName =  "系统";
        invokeMethod(entityList, "zip");

        entityList.forEach(entity -> {
            makeCreate(entity, loginName);
        });
        return mapper.insertList(entityList);
    }

    public int insertSelectiveList(List<T> entityList) {
        if (CollectionUtils.isEmpty(entityList)) {
            return 0;
        }
//        UserInfoModel userInfoModel = tokenUtil.getUserInfoByTenantContext();
//        final String loginName = userInfoModel != null ? userInfoModel.getUserName() : "系统";
        final String loginName =  "系统";
        invokeMethod(entityList, "zip");

        entityList.forEach(entity -> {
            makeCreate(entity, loginName);
        });
        return mapper.insertSelectiveList(entityList);
    }

    public int deleteByPrimaryKey(Object primaryKey) {
        return mapper.deleteByPrimaryKey(primaryKey);
    }

    public int delete(T entity) {
        return mapper.delete(entity);
    }

    public int deleteByExample(Example example) {
        return mapper.deleteByExample(example);
    }

    public List<T> selectByExample(Example example) {
        List<T> list = mapper.selectByExample(example);
        invokeMethod(list, "unzip");
        return list;
    }

//    public int truncate() {
//        UserInfoModel userInfoModel = tokenUtil.getUserInfoByTenantContext();
//        if (BooleanUtil.BOOLEAN_TRUE.equals(userInfoModel.getIsSuperAdmin())) {
//            log.info("truncate---{}--{}", userInfoModel, LocalDateTime.now().toString());
//            return mapper.truncate();
//        }
//        return -1;
//    }

    public int init() {
        return -1;
    }

    //带排序的查询
    public List<T> selectByExample(Example example, List<SortQuery> sortList) {
        if (CollectionUtils.isNotEmpty(sortList)) {
            for (SortQuery sortQuery : sortList) {
                if (StringUtils.isNotBlank(sortQuery.getColumn())) {
                    if ("desc".equals(sortQuery.getOrder())) {
                        example.orderBy(sortQuery.getColumn()).desc();
                    } else {
                        example.orderBy(sortQuery.getColumn()).asc();
                    }
                }
            }
        }

        return mapper.selectByExample(example);
    }

    public List<T> selectAll() {
        List<T> list = mapper.selectAll();
        invokeMethod(list, "unzip");
        return list;
    }

    public PageDTO findPageListByExample(Example example) {
        List<T> list = selectByExample(example);
        invokeMethod(list, "unzip");

        PageInfo pageInfo = new PageInfo<>(list);
        return new PageDTO(pageInfo);
    }

    public PageDTO findPageListByExample(Example example, List<SortQuery> sortList) {
        List<T> list = selectByExample(example, sortList);
        invokeMethod(list, "unzip");
        PageInfo pageInfo = new PageInfo<>(list);

        return new PageDTO(pageInfo);
    }

    public Integer selectCount(T entity) {
        return mapper.selectCount(entity);
    }

    public Integer selectCountByExample(Example example) {
        return mapper.selectCountByExample(example);
    }

    public T selectOneByExample(Example example) {
        T model = mapper.selectOneByExample(example);
        invokeMethod(model, "unzip");
        return model;
    }

    public T selectFirstByExample(Example example) {
        List<T> list = mapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(list)) {
            T model = list.get(0);
            invokeMethod(model, "unzip");
            return model;
        } else {
            return null;
        }
    }

    private void makeCreate(T entity, String loginName) {
        if (entity instanceof CreateModel) {
            ((CreateModel) entity).setId(null);

            if (((CreateModel) entity).getCreateTime() == null) {
                ((CreateModel) entity).setCreateTime(new Date());
            }
            if (((CreateModel) entity).getCreator() == null) {
                ((CreateModel) entity).setCreator(loginName);
            }
        } else if (entity instanceof UUIDCreateModel) {
            ((UUIDCreateModel) entity).setId(null);
            if (((UUIDCreateModel) entity).getCreateTime() == null) {
                ((UUIDCreateModel) entity).setCreateTime(new Date());
            }
            if (((UUIDCreateModel) entity).getCreator() == null) {
                ((UUIDCreateModel) entity).setCreator(loginName);
            }
        } else if (entity instanceof CreateTimeModel) {
            ((CreateTimeModel) entity).setId(null);
            if (((CreateTimeModel) entity).getCreateTime() == null) {
                ((CreateTimeModel) entity).setCreateTime(System.currentTimeMillis());
            }
            if (((CreateTimeModel) entity).getCreator() == null) {
                ((CreateTimeModel) entity).setCreator(loginName);
            }
        }


    }

    private void makeEdit(T entity, String loginName) {
        if (entity instanceof BaseModel) {
            ((BaseModel) entity).setEditTime(new Date());
            ((BaseModel) entity).setEditor(loginName);
        } else if (entity instanceof UUIDBaseModel) {
            ((UUIDBaseModel) entity).setEditTime(new Date());
            ((UUIDBaseModel) entity).setEditor(loginName);

        } else if (entity instanceof BaseTimeModel) {
            ((BaseTimeModel) entity).setEditTime(System.currentTimeMillis());
            ((BaseTimeModel) entity).setEditor(loginName);

        }
    }

    private void invokeMethod(List<T> entityList, String methodName) {
        try {
            if (CollectionUtils.isEmpty(entityList)) {
                return;
            }
            T entity = entityList.get(0);
            Method method;
            Class entityClass = entity.getClass();
            method = entityClass.getMethod(methodName);
            method.setAccessible(true);
            for (T model : entityList) {
                method.invoke(model);
            }
        } catch (Exception e) {
        }

    }

    private void invokeMethod(T entity, String methodName) {
        Method method;
        try {
            Class entityClass = entity.getClass();
            method = entityClass.getMethod(methodName);
            method.setAccessible(true);
            method.invoke(entity);
        } catch (Exception e) {

        }

    }


}
